package com.gitee.wsl.io.channel.read

import com.gitee.wsl.annotation.InternalAPI
import com.gitee.wsl.io.channel.CloseToken
import com.gitee.wsl.io.remaining
import kotlinx.io.IOException
import kotlinx.io.Source
import kotlin.concurrent.Volatile


internal class SourceByteReadChannel(private val source: Source) : ByteReadChannel {
    @Volatile
    private var closed: CloseToken? = null

    override val closedCause: Throwable?
        get() = closed?.cause

    override val isClosedForRead: Boolean
        get() = source.exhausted()

    @InternalAPI
    override val readBuffer: Source
        get() {
            closedCause?.let { throw it }
            return source
        }

    override suspend fun awaitContent(min: Int): Boolean {
        closedCause?.let { throw it }
        return source.remaining >= min
    }

    override fun cancel(cause: Throwable?) {
        if (closed != null) return
        source.close()
        closed = CloseToken(IOException(cause?.message ?: "Channel was cancelled", cause))
    }
}